---
title: "If-Else & Loops"
description: "If, else, ternary, for, and while"
canonical: "/docs/manual/control-flow"
section: "Language Features"
order: 14
---

# If-Else & Loops

ReScript supports `if`, `else`, ternary expression (`a ? b : c`), `for` and `while`.

The `switch` pattern has a default case too, just like many other functional languages. Read more about [pattern-matching & destructuring](./pattern-matching-destructuring.mdx). there.

## If-Else & Ternary

Unlike its JavaScript counterpart, ReScript's `if` is an expression; they evaluate to their body's content:

<CodeTab labels={["ReScript", "JS Output"]}>

```res
let message = if isMorning {
  "Good morning!"
} else {
  "Hello!"
}
```

```js
var message = isMorning ? "Good morning!" : "Hello!";
```

</CodeTab>

**Note:** an `if-else` expression without the final `else` branch implicitly gives `()` (aka the `unit` type). So this:

<CodeTab labels={["ReScript", "JS Output"]}>

```res
if showMenu {
  displayMenu()
}
```

```js
if (showMenu) {
  displayMenu();
}
```

</CodeTab>

is basically the same as:

<CodeTab labels={["ReScript", "JS Output"]}>

```res
if showMenu {
  displayMenu()
} else {
  ()
}
```

```js
if (showMenu) {
  displayMenu();
}
```

</CodeTab>

Here's another way to look at it. This is clearly wrong:

```res
let result = if showMenu {
  1 + 2
}
```

It'll give a type error, saying basically that the implicit `else` branch has the type `unit` while the `if` branch has type `int`. Intuitively, this makes sense: what would `result`'s value be, if `showMenu` was `false`?

We also have ternary sugar, but **we encourage you to prefer if-else when possible**.

<CodeTab labels={["ReScript", "JS Output"]}>

```res
let message = isMorning ? "Good morning!" : "Hello!"
```

```js
var message = isMorning ? "Good morning!" : "Hello!";
```

</CodeTab>

**`if-else` and ternary are much less used** in ReScript than in other languages; [Pattern-matching](./pattern-matching-destructuring.mdx) kills a whole category of code that previously required conditionals.

## For Loops

For loops iterate from a starting value up to (and including) the ending value.

<CodeTab labels={["ReScript", "JS Output"]}>

```res
for i in startValueInclusive to endValueInclusive {
  Console.log(i)
}
```

```js
for (var i = startValueInclusive; i <= endValueInclusive; ++i) {
  console.log(i);
}
```

</CodeTab>

<CodeTab labels={["ReScript", "JS Output"]}>

```res example
// prints: 1 2 3, one per line
for x in 1 to 3 {
  Console.log(x)
}
```

```js
for (var x = 1; x <= 3; ++x) {
  console.log(x);
}
```

</CodeTab>

You can make the `for` loop count in the opposite direction by using `downto`.

<CodeTab labels={["ReScript", "JS Output"]}>

```res
for i in startValueInclusive downto endValueInclusive {
  Console.log(i)
}
```

```js
for (var i = startValueInclusive; i >= endValueInclusive; --i) {
  console.log(i);
}
```

</CodeTab>

<CodeTab labels={["ReScript", "JS Output"]}>

```res example
// prints: 3 2 1, one per line
for x in 3 downto 1 {
  Console.log(x)
}
```

```js
for (var x = 3; x >= 1; --x) {
  console.log(x);
}
```

</CodeTab>

## While Loops

While loops execute its body code block while its condition is true.

<CodeTab labels={["ReScript", "JS Output"]}>

```res
while testCondition {
  // body here
}
```

```js
while (testCondition) {
  // body here
}
```

</CodeTab>

### Tips & Tricks

There's no loop-breaking `break` keyword (nor early `return` from functions, for that matter) in ReScript. However, we can break out of a while loop easily through using a [mutable binding](./mutation.mdx).

<CodeTab labels={["ReScript", "JS Output"]}>

```res example
let break = ref(false)

while !break.contents {
  if Math.random() > 0.3 {
    break := true
  } else {
    Console.log("Still running")
  }
}
```

```js
var $$break = {
  contents: false,
};

while (!$$break.contents) {
  if (Math.random() > 0.3) {
    $$break.contents = true;
  } else {
    console.log("Still running");
  }
}
```

</CodeTab>
